package com.gid.rcflightlogger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class DatabaseBackupActivity extends BaseActivity {
	
	public static final String package_name = "com.gid.rcflightlogger";
	
	private  String mDBfile =  ""; //"/data/" + package_name + "/databases/" + BaseActivity.DB_NAME
	private String mBackupDir = ""; //sdcard/package_name/
	
	private final int DIALOG_ID_RESTORE_FILE_SELECT = 1;
	
	private boolean mExternalStorageAvailable = false;
	private boolean mExternalStorageWriteable = false;
	
	private ArrayList<String> mRestoreFiles;
	
	private Button mBackup;
	private Button mRestore;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_dbbackuprestore);
        mCurrentMenuID = R.id.menu_main_more_backuprestore;
        
        mRestoreFiles = new ArrayList<String>();
        
        mBackup = (Button) findViewById(R.id.dbbackuprestore_btn_backup);
        mBackup.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
		        backup_db();
			}
		});
        
        mRestore = (Button) findViewById(R.id.dbbackuprestore_btn_restore);
        mRestore.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				restore_db_prepare();
			}
		});
	}
	
	void updateStorageStatus()
	{
		//update various strings
		mDBfile = Environment.getDataDirectory().toString() + "/data/" + package_name + "/databases/" + BaseActivity.DB_NAME;
		mBackupDir = Environment.getExternalStorageDirectory().toString() + "/" + package_name + "/";
	
		//check external storage
		String state = Environment.getExternalStorageState();
		Log.i(LOG_TAG, "External storage state " + state);
		
		if (Environment.MEDIA_MOUNTED.equals(state))
		{
		    mExternalStorageAvailable = true;
		    mExternalStorageWriteable = true;
		}
		else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {

		    mExternalStorageAvailable = true;
		    mExternalStorageWriteable = false;
		}
		else
		{
		    // Something else is wrong. It may be one of many other states, but all we need
		    //  to know is we can neither read nor write
		    mExternalStorageAvailable = false;
		    mExternalStorageWriteable = false;
		}
	}
	
	//updates filename on return true
	boolean backup_db()
	{
		Log.i(LOG_TAG, "Trying DB backup");
		
		updateStorageStatus();
		if (!mExternalStorageAvailable || !mExternalStorageWriteable)
		{
			myUtils.makeToast(this, "Database backup failed - no writable external storage found");
			return false;
		}

		File db = new File(mDBfile);
		if (!db.exists())
		{
			myUtils.makeToast(this, "Backup failed - internal database file not found");
			return false;
		}
		if (!db.canRead())
		{
			myUtils.makeToast(this, "Backup failed - internal database file not readable");
			return false;
		}
		
		File backupdir = new File(mBackupDir);
		if (!backupdir.exists() && !backupdir.mkdirs())
		{
			myUtils.makeToast(this, "Backup failed - folder could not be created: " + backupdir.toString());
			Log.i(LOG_TAG, "Backup failed - folder could not be created: " + backupdir.toString());
			return false;
		}
		
		String backupfilename =  (new SimpleDateFormat("yyyy-MM-dd-HH-mm")).format(new Date()) + ".db";
		File backupfile = new File(backupdir, backupfilename);

		try
		{
			FileChannel src = new FileInputStream(db).getChannel();
			FileChannel dst = new FileOutputStream(backupfile).getChannel();
			long bytes = dst.transferFrom(src, 0, src.size());
			src.close();
			dst.close();
			myUtils.makeToast(this, "Database backup successful - " + bytes + " bytes saved to " + backupfilename);
			Log.i(LOG_TAG, "Database backup successful - " + bytes + " bytes saved to " + backupfilename);
		}
		catch (Exception e)
		{
			Log.i(LOG_TAG, "DB backup exception: " + e.getMessage());
			return false;
		}
		return true;
	}
	
	boolean restore_db_prepare()
	{
		Log.i(LOG_TAG, "Trying DB restore");
		
		updateStorageStatus();
		
		if (!mExternalStorageAvailable)
		{
			myUtils.makeToast(this, "Database restore failed - external storage not found");
			return false;
		}
		
		File backupdir = new File(mBackupDir);
		if (!backupdir.exists() || !backupdir.canRead())
		{
			myUtils.makeToast(this, "Database restore failed - backup folder not found: " + backupdir.toString());
			Log.i(LOG_TAG, "Database restore failed - backup folder not found: " + backupdir.toString());
			return false;
		}
		
		//get list of backup file names
		mRestoreFiles.clear();
		File[] filelist = backupdir.listFiles();
		for (File f : filelist)
		{
			String filename = f.getName();
			if (filename.endsWith(".db"))
			{
				mRestoreFiles.add(filename);
				Log.i(LOG_TAG, "Database backup file found: " + filename);
			}
		}
		
		if (mRestoreFiles.isEmpty())
		{
			myUtils.makeToast(this, "Database restore failed - no backup files found in folder " + backupdir.toString());
			Log.i(LOG_TAG, "Database restore failed - no backup files found in folder " + backupdir.toString());
			return false;
		}
		
		showDialog(DIALOG_ID_RESTORE_FILE_SELECT);
		return true;
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id)
		{
		case DIALOG_ID_RESTORE_FILE_SELECT:
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle("Pick backup file to restore");
			//set custom view
			LinearLayout box = (LinearLayout)getLayoutInflater().inflate(R.layout.layout_dbrestoredialog, null);
		    RadioGroup rg = (RadioGroup) box.findViewById(R.id.dbrestoredialog_radio_group);
			builder.setView(box);
			
			builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id2) {
					RadioGroup rg = (RadioGroup) ((Dialog)dialog).findViewById(R.id.dbrestoredialog_radio_group);
					restore_db_from_backup(mRestoreFiles.get(rg.getCheckedRadioButtonId()));
					dialog.dismiss();
				}
			});
			builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					dialog.cancel();
				}
			});
		    
			
			return builder.create();
			
		default:
			return super.onCreateDialog(id);
		}
	}
	
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		super.onPrepareDialog(id, dialog);
		switch (id)
		{
		case DIALOG_ID_RESTORE_FILE_SELECT:
			RadioGroup rg = (RadioGroup) dialog.findViewById(R.id.dbrestoredialog_radio_group);
			rg.removeAllViews();
			for (int i = 0; i < mRestoreFiles.size(); i++)
			{
				RadioButton btn = new RadioButton(this);
				btn.setId(i);
				btn.setText(mRestoreFiles.get(i));
				btn.setChecked((i==0));
				rg.addView(btn); 
			} 
			break;
		default:
		}
	}
	
	boolean restore_db_from_backup(String filename)
	{
		File backupfile = new File(mBackupDir, filename);
		File db = new File(mDBfile);
		
		if (!backupfile.canRead())
		{
			Log.i(LOG_TAG, "Database restore failed - cannot read backup file :" + filename);
			return false;
		}
		
		if (db.exists() && !db.canWrite())
		{
			Log.i(LOG_TAG, "Database restore failed - cannot write to db file :" + mDBfile);
			return false;
		}
		
		try
		{
			FileChannel src = new FileInputStream(backupfile).getChannel();
			FileChannel dst = new FileOutputStream(db).getChannel();
			long bytes = dst.transferFrom(src, 0, src.size());
			src.close();
			dst.close();
			myUtils.makeToast(this, "Database restore successful - " + bytes + " bytes restore to " + mDBfile);
			Log.i(LOG_TAG, "Database restore successful - " + bytes + " bytes restore to " + mDBfile);
		}
		catch (Exception e)
		{
			Log.i(LOG_TAG, "DB restore exception: " + e.getMessage());
			return false;
		}
		return true;
	}
}
